#ifndef THINK_THINK_CONSOLE_INPUT_H
#define THINK_THINK_CONSOLE_INPUT_H

static char* think_console_input =
	"\n"
	"// +----------------------------------------------------------------------\n"
	"// | ThinkPHP [ WE CAN DO IT JUST THINK ]\n"
	"// +----------------------------------------------------------------------\n"
	"// | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.\n"
	"// +----------------------------------------------------------------------\n"
	"// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )\n"
	"// +----------------------------------------------------------------------\n"
	"// | Author: yunwuxin <448901948@qq.com>\n"
	"// +----------------------------------------------------------------------\n"
	"\n"
	"namespace think\\console;\n"
	"\n"
	"use think\\console\\input\\Argument;\n"
	"use think\\console\\input\\Definition;\n"
	"use think\\console\\input\\Option;\n"
	"\n"
	"class Input\n"
	"{\n"
	"\n"
	"    /**\n"
	"     * @var Definition\n"
	"     */\n"
	"    protected $definition;\n"
	"\n"
	"    /**\n"
	"     * @var Option[]\n"
	"     */\n"
	"    protected $options = [];\n"
	"\n"
	"    /**\n"
	"     * @var Argument[]\n"
	"     */\n"
	"    protected $arguments = [];\n"
	"\n"
	"    protected $interactive = true;\n"
	"\n"
	"    private $tokens;\n"
	"    private $parsed;\n"
	"\n"
	"    public function __construct($argv = null)\n"
	"    {\n"
	"        if (null === $argv) {\n"
	"            $argv = $_SERVER[\'argv\'];\n"
	"            // 去除命令名\n"
	"            array_shift($argv);\n"
	"        }\n"
	"\n"
	"        $this->tokens = $argv;\n"
	"\n"
	"        $this->definition = new Definition();\n"
	"    }\n"
	"\n"
	"    protected function setTokens(array $tokens)\n"
	"    {\n"
	"        $this->tokens = $tokens;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 绑定实例\n"
	"     * @param Definition $definition A InputDefinition instance\n"
	"     */\n"
	"    public function bind(Definition $definition)\n"
	"    {\n"
	"        $this->arguments  = [];\n"
	"        $this->options    = [];\n"
	"        $this->definition = $definition;\n"
	"\n"
	"        $this->parse();\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 解析参数\n"
	"     */\n"
	"    protected function parse()\n"
	"    {\n"
	"        $parseOptions = true;\n"
	"        $this->parsed = $this->tokens;\n"
	"        while (null !== $token = array_shift($this->parsed)) {\n"
	"            if ($parseOptions && \'\' == $token) {\n"
	"                $this->parseArgument($token);\n"
	"            } elseif ($parseOptions && \'--\' == $token) {\n"
	"                $parseOptions = false;\n"
	"            } elseif ($parseOptions && 0 === strpos($token, \'--\')) {\n"
	"                $this->parseLongOption($token);\n"
	"            } elseif ($parseOptions && \'-\' === $token[0] && \'-\' !== $token) {\n"
	"                $this->parseShortOption($token);\n"
	"            } else {\n"
	"                $this->parseArgument($token);\n"
	"            }\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 解析短选项\n"
	"     * @param string $token 当前的指令.\n"
	"     */\n"
	"    private function parseShortOption($token)\n"
	"    {\n"
	"        $name = substr($token, 1);\n"
	"\n"
	"        if (strlen($name) > 1) {\n"
	"            if ($this->definition->hasShortcut($name[0])\n"
	"                && $this->definition->getOptionForShortcut($name[0])->acceptValue()\n"
	"            ) {\n"
	"                $this->addShortOption($name[0], substr($name, 1));\n"
	"            } else {\n"
	"                $this->parseShortOptionSet($name);\n"
	"            }\n"
	"        } else {\n"
	"            $this->addShortOption($name, null);\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 解析短选项\n"
	"     * @param string $name 当前指令\n"
	"     * @throws \\RuntimeException\n"
	"     */\n"
	"    private function parseShortOptionSet($name)\n"
	"    {\n"
	"        $len = strlen($name);\n"
	"        for ($i = 0; $i < $len; ++$i) {\n"
	"            if (!$this->definition->hasShortcut($name[$i])) {\n"
	"                throw new \\RuntimeException(sprintf(\'The \"-%s\" option does not exist.\', $name[$i]));\n"
	"            }\n"
	"\n"
	"            $option = $this->definition->getOptionForShortcut($name[$i]);\n"
	"            if ($option->acceptValue()) {\n"
	"                $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));\n"
	"\n"
	"                break;\n"
	"            } else {\n"
	"                $this->addLongOption($option->getName(), null);\n"
	"            }\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 解析完整选项\n"
	"     * @param string $token 当前指令\n"
	"     */\n"
	"    private function parseLongOption($token)\n"
	"    {\n"
	"        $name = substr($token, 2);\n"
	"\n"
	"        if (false !== $pos = strpos($name, \'=\')) {\n"
	"            $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));\n"
	"        } else {\n"
	"            $this->addLongOption($name, null);\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 解析参数\n"
	"     * @param string $token 当前指令\n"
	"     * @throws \\RuntimeException\n"
	"     */\n"
	"    private function parseArgument($token)\n"
	"    {\n"
	"        $c = count($this->arguments);\n"
	"\n"
	"        if ($this->definition->hasArgument($c)) {\n"
	"            $arg = $this->definition->getArgument($c);\n"
	"\n"
	"            $this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token;\n"
	"\n"
	"        } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {\n"
	"            $arg = $this->definition->getArgument($c - 1);\n"
	"\n"
	"            $this->arguments[$arg->getName()][] = $token;\n"
	"        } else {\n"
	"            throw new \\RuntimeException(\'Too many arguments.\');\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 添加一个短选项的值\n"
	"     * @param string $shortcut 短名称\n"
	"     * @param mixed  $value    值\n"
	"     * @throws \\RuntimeException\n"
	"     */\n"
	"    private function addShortOption($shortcut, $value)\n"
	"    {\n"
	"        if (!$this->definition->hasShortcut($shortcut)) {\n"
	"            throw new \\RuntimeException(sprintf(\'The \"-%s\" option does not exist.\', $shortcut));\n"
	"        }\n"
	"\n"
	"        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 添加一个完整选项的值\n"
	"     * @param string $name  选项名\n"
	"     * @param mixed  $value 值\n"
	"     * @throws \\RuntimeException\n"
	"     */\n"
	"    private function addLongOption($name, $value)\n"
	"    {\n"
	"        if (!$this->definition->hasOption($name)) {\n"
	"            throw new \\RuntimeException(sprintf(\'The \"--%s\" option does not exist.\', $name));\n"
	"        }\n"
	"\n"
	"        $option = $this->definition->getOption($name);\n"
	"\n"
	"        if (false === $value) {\n"
	"            $value = null;\n"
	"        }\n"
	"\n"
	"        if (null !== $value && !$option->acceptValue()) {\n"
	"            throw new \\RuntimeException(sprintf(\'The \"--%s\" option does not accept a value.\', $name, $value));\n"
	"        }\n"
	"\n"
	"        if (null === $value && $option->acceptValue() && count($this->parsed)) {\n"
	"            $next = array_shift($this->parsed);\n"
	"            if (isset($next[0]) && \'-\' !== $next[0]) {\n"
	"                $value = $next;\n"
	"            } elseif (empty($next)) {\n"
	"                $value = \'\';\n"
	"            } else {\n"
	"                array_unshift($this->parsed, $next);\n"
	"            }\n"
	"        }\n"
	"\n"
	"        if (null === $value) {\n"
	"            if ($option->isValueRequired()) {\n"
	"                throw new \\RuntimeException(sprintf(\'The \"--%s\" option requires a value.\', $name));\n"
	"            }\n"
	"\n"
	"            if (!$option->isArray()) {\n"
	"                $value = $option->isValueOptional() ? $option->getDefault() : true;\n"
	"            }\n"
	"        }\n"
	"\n"
	"        if ($option->isArray()) {\n"
	"            $this->options[$name][] = $value;\n"
	"        } else {\n"
	"            $this->options[$name] = $value;\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取第一个参数\n"
	"     * @return string|null\n"
	"     */\n"
	"    public function getFirstArgument()\n"
	"    {\n"
	"        foreach ($this->tokens as $token) {\n"
	"            if ($token && \'-\' === $token[0]) {\n"
	"                continue;\n"
	"            }\n"
	"\n"
	"            return $token;\n"
	"        }\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检查原始参数是否包含某个值\n"
	"     * @param string|array $values 需要检查的值\n"
	"     * @return bool\n"
	"     */\n"
	"    public function hasParameterOption($values)\n"
	"    {\n"
	"        $values = (array) $values;\n"
	"\n"
	"        foreach ($this->tokens as $token) {\n"
	"            foreach ($values as $value) {\n"
	"                if ($token === $value || 0 === strpos($token, $value . \'=\')) {\n"
	"                    return true;\n"
	"                }\n"
	"            }\n"
	"        }\n"
	"\n"
	"        return false;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取原始选项的值\n"
	"     * @param string|array $values  需要检查的值\n"
	"     * @param mixed        $default 默认值\n"
	"     * @return mixed The option value\n"
	"     */\n"
	"    public function getParameterOption($values, $default = false)\n"
	"    {\n"
	"        $values = (array) $values;\n"
	"        $tokens = $this->tokens;\n"
	"\n"
	"        while (0 < count($tokens)) {\n"
	"            $token = array_shift($tokens);\n"
	"\n"
	"            foreach ($values as $value) {\n"
	"                if ($token === $value || 0 === strpos($token, $value . \'=\')) {\n"
	"                    if (false !== $pos = strpos($token, \'=\')) {\n"
	"                        return substr($token, $pos + 1);\n"
	"                    }\n"
	"\n"
	"                    return array_shift($tokens);\n"
	"                }\n"
	"            }\n"
	"        }\n"
	"\n"
	"        return $default;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 验证输入\n"
	"     * @throws \\RuntimeException\n"
	"     */\n"
	"    public function validate()\n"
	"    {\n"
	"        if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) {\n"
	"            throw new \\RuntimeException(\'Not enough arguments.\');\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检查输入是否是交互的\n"
	"     * @return bool\n"
	"     */\n"
	"    public function isInteractive()\n"
	"    {\n"
	"        return $this->interactive;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置输入的交互\n"
	"     * @param bool\n"
	"     */\n"
	"    public function setInteractive($interactive)\n"
	"    {\n"
	"        $this->interactive = (bool) $interactive;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取所有的参数\n"
	"     * @return Argument[]\n"
	"     */\n"
	"    public function getArguments()\n"
	"    {\n"
	"        return array_merge($this->definition->getArgumentDefaults(), $this->arguments);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 根据名称获取参数\n"
	"     * @param string $name 参数名\n"
	"     * @return mixed\n"
	"     * @throws \\InvalidArgumentException\n"
	"     */\n"
	"    public function getArgument($name)\n"
	"    {\n"
	"        if (!$this->definition->hasArgument($name)) {\n"
	"            throw new \\InvalidArgumentException(sprintf(\'The \"%s\" argument does not exist.\', $name));\n"
	"        }\n"
	"\n"
	"        return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)\n"
	"            ->getDefault();\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置参数的值\n"
	"     * @param string $name  参数名\n"
	"     * @param string $value 值\n"
	"     * @throws \\InvalidArgumentException\n"
	"     */\n"
	"    public function setArgument($name, $value)\n"
	"    {\n"
	"        if (!$this->definition->hasArgument($name)) {\n"
	"            throw new \\InvalidArgumentException(sprintf(\'The \"%s\" argument does not exist.\', $name));\n"
	"        }\n"
	"\n"
	"        $this->arguments[$name] = $value;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检查是否存在某个参数\n"
	"     * @param string|int $name 参数名或位置\n"
	"     * @return bool\n"
	"     */\n"
	"    public function hasArgument($name)\n"
	"    {\n"
	"        return $this->definition->hasArgument($name);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取所有的选项\n"
	"     * @return Option[]\n"
	"     */\n"
	"    public function getOptions()\n"
	"    {\n"
	"        return array_merge($this->definition->getOptionDefaults(), $this->options);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取选项值\n"
	"     * @param string $name 选项名称\n"
	"     * @return mixed\n"
	"     * @throws \\InvalidArgumentException\n"
	"     */\n"
	"    public function getOption($name)\n"
	"    {\n"
	"        if (!$this->definition->hasOption($name)) {\n"
	"            throw new \\InvalidArgumentException(sprintf(\'The \"%s\" option does not exist.\', $name));\n"
	"        }\n"
	"\n"
	"        return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置选项值\n"
	"     * @param string      $name  选项名\n"
	"     * @param string|bool $value 值\n"
	"     * @throws \\InvalidArgumentException\n"
	"     */\n"
	"    public function setOption($name, $value)\n"
	"    {\n"
	"        if (!$this->definition->hasOption($name)) {\n"
	"            throw new \\InvalidArgumentException(sprintf(\'The \"%s\" option does not exist.\', $name));\n"
	"        }\n"
	"\n"
	"        $this->options[$name] = $value;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 是否有某个选项\n"
	"     * @param string $name 选项名\n"
	"     * @return bool\n"
	"     */\n"
	"    public function hasOption($name)\n"
	"    {\n"
	"        return $this->definition->hasOption($name) && isset($this->options[$name]);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 转义指令\n"
	"     * @param string $token\n"
	"     * @return string\n"
	"     */\n"
	"    public function escapeToken($token)\n"
	"    {\n"
	"        return preg_match(\'{^[\\w-]+$}\', $token) ? $token : escapeshellarg($token);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 返回传递给命令的参数的字符串\n"
	"     * @return string\n"
	"     */\n"
	"    public function __toString()\n"
	"    {\n"
	"        $tokens = array_map(function ($token) {\n"
	"            if (preg_match(\'{^(-[^=]+=)(.+)}\', $token, $match)) {\n"
	"                return $match[1] . $this->escapeToken($match[2]);\n"
	"            }\n"
	"\n"
	"            if ($token && \'-\' !== $token[0]) {\n"
	"                return $this->escapeToken($token);\n"
	"            }\n"
	"\n"
	"            return $token;\n"
	"        }, $this->tokens);\n"
	"\n"
	"        return implode(\' \', $tokens);\n"
	"    }\n"
	"}\n"
	"\n"
;
#endif